package com.github.kezhenxu94.acs.common;

import java.io.Serializable;
import java.util.Properties;
import java.util.logging.Logger;

import com.github.kezhenxu94.acs.math.Matrix;
import com.github.kezhenxu94.acs.utils.RandomGenerator;

/**
 * Created by kezhenxu at Dec 18, 2016
 *
 * @author kezhenxu (kezhenxu94@163.com)
 */
public class Environment implements Serializable {
	private static final long serialVersionUID = 1L;

	private static final Logger logger = Logger.getLogger(Environment.class.getName());

	private static final String	DEFAULT_INITIAL_PHEROMONE	= ".01";
	private static final String	DEFAULT_EVAPORATION_RATE	= ".8";
	private static final String	DEFAULT_MAX_ITERATION		= "10";
	private static final String	DEFAULT_CLUSTER_COUNT		= "3";
	private static final String	DEFAULT_COLONY_SIZE			= "10";

	private double	evaporationRate;
	private double	initialPheromone;
	private int		maxIteration;
	private int		colonySize;
	private int		clusterCount;

	protected RandomGenerator	randomGenerator;
	protected Properties		properties;

	protected Matrix	dataSet;
	protected Matrix	pheromone;

	public Environment(Properties properties) {
		this.randomGenerator = new RandomGenerator();
		this.properties = properties;

		this.maxIteration = Integer.valueOf(getProperty("max.iteration", DEFAULT_MAX_ITERATION));
		this.colonySize = Integer.valueOf(getProperty("colony.size", DEFAULT_COLONY_SIZE));
		this.evaporationRate = Double.valueOf(getProperty("evaporation.rate", DEFAULT_EVAPORATION_RATE));
		this.clusterCount = Integer.valueOf(getProperty("cluster.count", DEFAULT_CLUSTER_COUNT));
		this.initialPheromone = Double.valueOf(getProperty("initial.pheromone", DEFAULT_INITIAL_PHEROMONE));

		logger.info(parameters());
	}

	public void init() {
		initPheromone();
	}

	private void initPheromone() {
		this.pheromone = new Matrix(getRowCount(), getClusterCount(), 0);
		for (int i = 0; i < getRowCount(); i++) {
			for (int j = 0; j < getClusterCount(); j++) {
				pheromone.set(i, j, getInitialPheromone());
			}
		}
	}

	public String parameters() {
		StringBuilder sb = new StringBuilder();
		sb.append("[Parameters: ")
				.append("max.iteration=").append(maxIteration)
				.append(", colony.size=").append(colonySize)
				.append(", evaporation.rate=").append(evaporationRate)
				.append(", cluster.count=").append(clusterCount)
				.append("]");
		return sb.toString();
	}

	public int getMaxIteration() {
		return maxIteration;
	}

	public int getColonySize() {
		return colonySize;
	}

	public int getClusterCount() {
		return clusterCount;
	}

	public double getEvaporationRate() {
		return evaporationRate;
	}

	public double getInitialPheromone() {
		return initialPheromone;
	}

	public String getProperty(String key) {
		return properties.getProperty(key);
	}

	public String getProperty(String key, String defaultValue) {
		return properties.getProperty(key, defaultValue);
	}

	public Matrix getPheromone() {
		return pheromone;
	}

	public void setPheromone(Matrix pheromone) {
		this.pheromone = pheromone;
	}

	public RandomGenerator getRandomGenerator() {
		return randomGenerator;
	}

	public void setDataSet(Matrix dataSet) {
		this.dataSet = dataSet;
	}

	public Matrix getDataSet() {
		return dataSet;
	}

	public int getRowCount() {
		return dataSet.getRowCount();
	}

	public int getColumnCount() {
		return dataSet.getColumnCount();
	}
}
